package com.zjl.redis.第16章_分布式锁;

import cn.hutool.core.util.IdUtil;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
import org.junit.Test;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;

/**
 * 运行顺序
 *      模拟1
 *      模拟分布式加锁2和3
 *      模拟分布式加锁2和3
 *      模拟4
 *
 * redis分布式锁 需要克服
 *      1.宕机与过期+防止死锁
 *      2.防止误删key的问题
 *      3.Lua保证原子性
 *      4.可重入锁+设计模式
 *      5.自动续期
 *
 */
public class B4_自定义工厂锁 {

    public static RedisCommands<String, String> getRedisCommands() {
        //构建 配置
        RedisURI redis2 = RedisURI.builder()
                .redis("82.157.71.243", 6379)//设置 ip 端口
                .withHost("82.157.71.243")//设置 ip
                .withPort(6379)//设置  端口
                .withAuthentication("default", "er485g96er8")//设置 用户名密码
                .withPassword("er485g96er8")//设置 密码
                .build();

        //连接 reids
        RedisClient redisClient = RedisClient.create(redis2);
        StatefulRedisConnection<String, String> connect = redisClient.connect();
        //创建 操作类
        RedisCommands<String, String> sync = connect.sync();//同步的连接
        return sync;
    }

    private static String AMT = "amt";
    private static String LOCK = "LOCK";
    private static int num = 100;
    private static int fbsNum = 2;

    public static void main(String[] args) throws InterruptedException, UnknownHostException {
        System.out.println(Thread.currentThread().getName());
        System.out.println(Thread.currentThread().getId());
        InetAddress inetAddress = InetAddress.getLocalHost();
        String ipAddress = inetAddress.getHostAddress();
        System.out.println(ipAddress);

        ExecutorService threadPool = new ThreadPoolExecutor(10, 10, 2L, TimeUnit.SECONDS, new LinkedBlockingDeque<>(10000));
        RedisCommands<String, String> redis = getRedisCommands();
        AtomicInteger atomicInteger = new AtomicInteger(0);//目的是 线程啥时候停止,没有其他目的

        System.out.println(redis.hgetall(LOCK));
        redis.del(LOCK);
        Lock redisLock = new RedisLock(redis,LOCK);
        for (int i = 0; i < 100; i++) {
            threadPool.execute(()->{
                try {

                    redisLock.lock();
                    atomicInteger.incrementAndGet();

                } finally {
                    redisLock.unlock();
                }
            });
        }
        while (atomicInteger.get() < 100) {
            System.out.println(atomicInteger.get());
            TimeUnit.SECONDS.sleep(1);
        }
        threadPool.shutdown();
        System.out.println("执行完");
        return;

    }

}
